#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

#include "dao.h"
#include "filter.h"
#include "http.h"
#include "util.h"

#define MYPORT 80 /*define user connection port*/
#define BACKLOG 10 /*how many connections are waiting*/

char name[10][128],value[10][128];
void sendFile(char* fileAddr, int new_fd);

int sockfd = 0;

void sign_process_kill(int signal)
{
  shutdown(sockfd, SHUT_RDWR);
  return ; 
}

int main(int argc, char* argv)
{
  int i, new_fd;/*listen no sockfd, new connection on new_fd*/
  struct sockaddr_in my_addr;
  struct sockaddr_in their_addr;
  int sin_size;

  signal(SIGKILL, sign_process_kill);
 
  if(sem_init(&OK_to_access, 1, 1))
  {
    printf("Could not initialization a semphore.\n");
    return -1; 
  }  

  printf("server starting...\n");	
  if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    perror("socket");
    exit(1);
  }

  my_addr.sin_family = AF_INET;
  my_addr.sin_port = htons(MYPORT);
  my_addr.sin_addr.s_addr = INADDR_ANY;
  bzero(&(my_addr.sin_zero), sizeof(my_addr.sin_zero));

  if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == 1)
  {
    perror("bind");
    exit(1);
  }

  if(listen(sockfd, BACKLOG) == -1)
  {
    perror("listening");
    exit(1);
  }

  printf("server started...\n");

  pid_t pid;
  while(1)
  {
    sin_size = sizeof(struct sockaddr_in);
    if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
    {
      perror("accept");
      continue;
    }

    if(1)
    {
#ifdef _DEBUG
  printf("client: coming...\n");
  printf("client IP:%s\n", inet_ntoa(their_addr.sin_addr));
#endif
      char buffer[2048], buff[2048];
      int len = recv(new_fd, buffer, sizeof(buffer), 0);
      bzero(buff, sizeof(buff));
      if(strlen(buffer) < 3)
      {
        sendFile("/Login.html", new_fd);
        shutdown(new_fd, SHUT_RDWR);
      }
      strcpy(buff, fileAddress(buffer));

#ifdef _DEBUG	
  printf("-------------\n%s\n------------------------\n", buff);
#endif

      //这是一个请求文件的请求	
      if(charindex(buff, '.') != -1)
      {

#ifdef _DEBUG
  printf(". request coming...\n");
  printf("%s\n", buff);
#endif
        sendFile(fileAddress(buffer), new_fd);					
      }
      else if(!strcmp("/", buff))
      {
        //这是一个请求根目录的请求

#ifdef _DEBUG
  printf("/ request coming...\n");
#endif

        sendFile("/Login.html", new_fd);
      }
      else 
      {
        //这是其他请求
        char requri[128];
	printf("other request:::::%s\n", buff);
        if(!get_post_uri(buff, requri))
        {
          return ;
        }
	
        //这是一个用户登录的请求
        if(!strcmp(requri, "/Login"))
        {
          int par_size = get_request_params(buffer);	
				
          if(par_size == 2)
          {
            if(strcmp(name[0],"username") == 0 && strcmp(name[1],"passwd") == 0)
            {
              if(IsExit(value[0], value[1]))
              {
                allow_user(inet_ntoa(their_addr.sin_addr)); 

#ifdef _DEBUG
  printf("allow user succeed.\n");
#endif
                sendFile("/Timer.html", new_fd);
              }
	      else
              {
                sendFile("/Login.html", new_fd);
                shutdown(new_fd, SHUT_RDWR);
              } 
            }
          }
          else
          {
            sendFile("/Login.html", new_fd);
          }
        }
        else if(!strcmp(requri, "/out"))
        {

#ifdef _DEBUG
  printf("Logout invoke!");
#endif
          char ch[100];
          printf("logout invoke..\n");
          sendFile("/Login.html", new_fd);
//          deny_user(inet_ntoa(their_addr.sin_addr));
          sprintf(ch, "iptables -D PREROUTING  -t nat -s %s -j ACCEPT", inet_ntoa(their_addr.sin_addr));

#ifdef _DEBUG
  printf("ch: %s\n", ch);
#endif
    
          system(ch);
          shutdown(new_fd, SHUT_RDWR);
#ifdef _DEBUG
  printf("deny user succeed.\n");
#endif
        }
        else
        {

#ifdef _DEBUG
  printf("else invoke.\n");
#endif

          sendFile("/Login.html", new_fd);
          shutdown(new_fd, SHUT_RDWR);
        }
      }

#ifdef _DEBUG
  printf("before close new_fd\n");
#endif

      shutdown(new_fd, SHUT_RDWR);
      bzero(buffer, sizeof(buffer));
    }
#ifdef _DEBUG
  printf("after close new_fd\n");
#endif
  }
  
  sem_destroy(&OK_to_access);
  shutdown(sockfd, SHUT_RDWR);
}

void sendFile(char* fileAddr, int new_fd)
{
  char dir[1024] = "/home/tangwoyuan";
  int fd, size;
  char buffer[2048];
	
  strcat(dir, fileAddr);

#ifdef _DEBUG
  printf("file address:%s\n", dir);
#endif

  FILE* fp = fopen(dir, "r");
  if(NULL == fp)
  {
    printf("Not Found");
    return ;
  }

  char response[1024];
  int file_block_length = 0;

  if(!get_response_header(dir, response))
    return ;
  send(new_fd, response, strlen(response), 0);
	
  while((file_block_length = fread(buffer, sizeof(char), 2048, fp)) != EOF)
  {

#ifdef _DEBUG
  printf("file_block_length = %d\n", file_block_length);
#endif

    if(file_block_length == 0)
      break;

    if(send(new_fd, buffer, file_block_length, 0) < 0)
    {
      printf("Send File Failed\n", dir);
    }
    bzero(buffer, 2048);
  }
  fclose(fp);

#ifdef _DEBUG
  printf("File Transfer Finished\n");
#endif

  return ;
}
